import {ServiceImplementation} from './dbusService.js';
+import {ScreencastErrors, ScreencastError} from './misc/dbusErrors.js';
import {loadInterfaceXML, loadSubInterfaceXML} from './misc/dbusUtils.js';
import * as Signals from './misc/signals.js';
}
}
- _bailOutOnError(error) {
+ _bailOutOnError(message, errorDomain = ScreencastErrors, errorCode = ScreencastError.RECORDER_ERROR) {
+ const error = new GLib.Error(errorDomain, errorCode, message);
+
this._teardownPipeline();
this._unwatchSender();
this._stopSession();
- log(`Recorder error: ${error.message}`);
-
if (this._startRequest) {
this._startRequest.reject(error);
delete this._startRequest;
this.emit('error', error);
}
- _handleFatalPipelineError(message) {
+ _handleFatalPipelineError(message, errorDomain, errorCode) {
this._pipelineState = PipelineState.ERROR;
- this._bailOutOnError(new Error(`Fatal pipeline error: ${message}`));
+ this._bailOutOnError(message, errorDomain, errorCode);
}
_senderVanished() {
- this._bailOutOnError(new Error('Sender has vanished'));
+ this._bailOutOnError('Sender has vanished');
}
_onSessionClosed() {
return; // We closed the session ourselves
this._sessionState = SessionState.STOPPED;
- this._bailOutOnError(new Error('Session closed unexpectedly'));
+ this._bailOutOnError('Session closed unexpectedly');
}
_initSession(sessionPath) {
_tryNextPipeline() {
const {done, value: pipelineConfig} = this._pipelineConfigs.next();
if (done) {
- this._handleFatalPipelineError('All pipelines failed to start');
+ this._handleFatalPipelineError('All pipelines failed to start',
+ ScreencastErrors, ScreencastError.ALL_PIPELINES_FAILED);
return;
}
case PipelineState.PLAYING:
this._addRecentItem();
- this._handleFatalPipelineError('Unexpected EOS message');
+ this._handleFatalPipelineError('Unexpected EOS message',
+ ScreencastErrors, ScreencastError.PIPELINE_ERROR);
break;
case PipelineState.FLUSHING:
break;
case PipelineState.PLAYING:
- case PipelineState.FLUSHING:
- // Everything else we can't handle, so error out
+ case PipelineState.FLUSHING: {
+ const [error] = message.parse_error();
this._handleFatalPipelineError(
- `GStreamer error while in state ${this._pipelineState}: ${message.parse_error()[0].message}`);
+ `GStreamer error while in state ${this._pipelineState}: ${error.message}`,
+ ScreencastErrors, ScreencastError.PIPELINE_ERROR);
+
break;
+ }
default:
break;
}
async ScreencastAsync(params, invocation) {
- let returnValue = [false, ''];
-
if (this._lockdownSettings.get_boolean('disable-save-to-disk')) {
- invocation.return_value(GLib.Variant.new('(bs)', returnValue));
+ invocation.return_error_literal(ScreencastErrors,
+ ScreencastError.SAVE_TO_DISK_DISABLED,
+ 'Saving to disk is disabled');
return;
}
const sender = invocation.get_sender();
if (this._recorders.get(sender)) {
- invocation.return_value(GLib.Variant.new('(bs)', returnValue));
+ invocation.return_error_literal(ScreencastErrors,
+ ScreencastError.ALREADY_RECORDING,
+ 'Service is already recording');
return;
}
invocation);
} catch (error) {
log(`Failed to create recorder: ${error.message}`);
- invocation.return_value(GLib.Variant.new('(bs)', returnValue));
+ invocation.return_error_literal(ScreencastErrors,
+ ScreencastError.RECORDER_ERROR,
+ error.message);
+
return;
}
try {
await recorder.startRecording();
- returnValue = [true, filePath];
+ invocation.return_value(GLib.Variant.new('(bs)', [true, filePath]));
} catch (error) {
log(`Failed to start recorder: ${error.message}`);
this._removeRecorder(sender);
- } finally {
- invocation.return_value(GLib.Variant.new('(bs)', returnValue));
+ if (error instanceof GLib.Error) {
+ invocation.return_gerror(error);
+ } else {
+ invocation.return_error_literal(ScreencastErrors,
+ ScreencastError.RECORDER_ERROR,
+ error.message);
+ }
+
+ return;
}
recorder.connect('error', (r, error) => {
+ log(`Fatal error while recording: ${error.message}`);
this._removeRecorder(sender);
this._dbusImpl.emit_signal('Error',
- new GLib.Variant('(s)', [error.message]));
+ new GLib.Variant('(ss)', [
+ Gio.DBusError.encode_gerror(error),
+ error.message,
+ ]));
});
}
async ScreencastAreaAsync(params, invocation) {
- let returnValue = [false, ''];
-
if (this._lockdownSettings.get_boolean('disable-save-to-disk')) {
- invocation.return_value(GLib.Variant.new('(bs)', returnValue));
+ invocation.return_error_literal(ScreencastErrors,
+ ScreencastError.SAVE_TO_DISK_DISABLED,
+ 'Saving to disk is disabled');
return;
}
const sender = invocation.get_sender();
if (this._recorders.get(sender)) {
- invocation.return_value(GLib.Variant.new('(bs)', returnValue));
+ invocation.return_error_literal(ScreencastErrors,
+ ScreencastError.ALREADY_RECORDING,
+ 'Service is already recording');
return;
}
invocation);
} catch (error) {
log(`Failed to create recorder: ${error.message}`);
- invocation.return_value(GLib.Variant.new('(bs)', returnValue));
+ invocation.return_error_literal(ScreencastErrors,
+ ScreencastError.RECORDER_ERROR,
+ error.message);
+
return;
}
try {
await recorder.startRecording();
- returnValue = [true, filePath];
+ invocation.return_value(GLib.Variant.new('(bs)', [true, filePath]));
} catch (error) {
log(`Failed to start recorder: ${error.message}`);
this._removeRecorder(sender);
- } finally {
- invocation.return_value(GLib.Variant.new('(bs)', returnValue));
+ if (error instanceof GLib.Error) {
+ invocation.return_gerror(error);
+ } else {
+ invocation.return_error_literal(ScreencastErrors,
+ ScreencastError.RECORDER_ERROR,
+ error.message);
+ }
+
+ return;
}
recorder.connect('error', (r, error) => {
+ log(`Fatal error while recording: ${error.message}`);
this._removeRecorder(sender);
this._dbusImpl.emit_signal('Error',
- new GLib.Variant('(s)', [error.message]));
+ new GLib.Variant('(ss)', [
+ Gio.DBusError.encode_gerror(error),
+ error.message,
+ ]));
});
}
Gio._promisify(Shell.Screenshot.prototype, 'screenshot_stage_to_content');
Gio._promisify(Shell.Screenshot, 'composite_to_stream');
+import {ScreencastErrors, ScreencastError} from '../misc/dbusErrors.js';
import {loadInterfaceXML} from '../misc/fileUtils.js';
import {DBusSenderChecker} from '../misc/util.js';
this._syncCastButton();
});
- this._screencastProxy.connectSignal('Error',
- () => this._screencastFailed());
+ this._screencastProxy.connectSignal('Error', (proxy, sender, [errorName, message]) =>
+ this._screencastFailed(Gio.DBusError.new_for_dbus_error(errorName, message)));
this._screencastProxy.connect('notify::g-name-owner', () => {
if (this._screencastProxy.g_name_owner)
if (!this._screencastInProgress)
return;
- this._screencastFailed();
+ this._screencastFailed(
+ new GLib.Error(ScreencastErrors, ScreencastError.SERVICE_CRASH,
+ 'Service crashed'));
});
this._lockdownSettings = new Gio.Settings({schema_id: 'org.gnome.desktop.lockdown'});
this._setScreencastInProgress(true);
try {
- const [success, path] = await method(
+ const [, path] = await method(
GLib.build_filenamev([
/* Translators: this is the folder where recorded
screencasts are stored. */
_('Screencast from %d %t.webm'),
]),
{'draw-cursor': new GLib.Variant('b', drawCursor)});
- if (!success)
- throw new Error();
+
this._screencastPath = path;
} catch (error) {
this._setScreencastInProgress(false);
this._showNotification(_('Screencast recorded'));
}
- _screencastFailed() {
+ _screencastFailed(error) {
+ console.error(`Screencast failed: ${error}`);
+
this._setScreencastInProgress(false);
// Translators: notification title.